﻿#include "ZNetControl.h"
#include "ZLoadingControl.h"
#include "ZImageFormat.h"

namespace ZuiLib
{

	ZRefCountedPtr<ZNetControlDownloader> ZNetControlDownloader::s_downloader;

	ZNetControlDownloader::ZNetControlDownloader(const DownloaderHints* hints)
		:Downloader(hints)
	{
	}

	ZRefCountedPtr<ZNetControlDownloader> ZNetControlDownloader::Instance()
	{
		if (!s_downloader)
		{
			DownloaderHints hints;
			hints.countOfMaxProcessingTasks = 3;
			hints.tempFileNameSuffix = "_tmp";
			hints.timeoutInSeconds = 20;
			s_downloader = new ZRefCountedObject<ZNetControlDownloader>(&hints);
		}
		return s_downloader;
	}

	void ZNetControlDownloader::ReleaseInstance()
	{
		s_downloader = NULL;
	}

	void ZNetControlDownloader::onDataTaskSuccess(const DownloadTask& task,
		std::vector<unsigned char>& data)
	{

	}

	void ZNetControlDownloader::onFileTaskSuccess(const DownloadTask& task)
	{
		ZNetControlDownloaderObserver* control = (ZNetControlDownloaderObserver*)task.GetUserData();
		control->OnFinishDownload(DownloadTask::ERROR_NO_ERROR, task.GetPath().c_str());
		control->GetRefPtr()->Release();
	}

	void ZNetControlDownloader::onTaskProgress(const DownloadTask& task,
		int64_t bytesReceived,
		int64_t totalBytesReceived,
		int64_t totalBytesExpected)
	{
		ZNetControlDownloaderObserver* control = (ZNetControlDownloaderObserver*)task.GetUserData();
		if (totalBytesExpected > 0)
			control->OnDownloadProgress((int)(totalBytesReceived * 100 / totalBytesExpected));
	}

	void ZNetControlDownloader::onTaskError(const DownloadTask& task,
		int errorCode,
		int errorCodeInternal,
		const std::string& errorStr)
	{
		ZNetControlDownloaderObserver* control = (ZNetControlDownloaderObserver*)task.GetUserData();
		control->OnFinishDownload(errorCode, task.GetPath().c_str());
		control->GetRefPtr()->Release();
	}

	//////////////////////////////////////////////////////////////////////

	ZNetImageControl::ZNetImageControl(void)
		:m_state(STATE_OK)
	{
		m_loadMaxSize.cx = m_loadMaxSize.cy = 0;
	}

	ZNetImageControl::~ZNetImageControl(void)
	{

	}

	const char* ZNetImageControl::GetClass() const
	{
		return "NetImageControl";
	}

	void* ZNetImageControl::GetInterface(const char* pstrName)
	{
		if (strcmp(pstrName, "NetImageControl") == 0)
			return this;
		else
			return ZContainer::GetInterface(pstrName);
	}

	void ZNetImageControl::PaintStatusImage(ZRenderer* render)
	{
		//下载图片
		if (m_state == STATE_UNLOAD) {
			AsynSchedule(schedule_selector_void(ZNetImageControl::UpdateState));
		}

		if (m_state == STATE_ERROR){
			if (!m_errorImage.IsEmpty() && !DrawImage(render, &m_errorImage))
				m_errorImage.Clear();
		}else {
			ZContainer::PaintStatusImage(render);
		}
	}

	void ZNetImageControl::UpdateState() {
		if (m_state == STATE_UNLOAD) {
			if (!m_url.IsEmpty()) {
				Download(m_url);
			}
			else if (!m_file.IsEmpty()) {
				LoadFile(m_file);
			}
			else {
				m_state = STATE_OK;
			}
		}
	}

	void ZNetImageControl::SetAttribute(const char* pstrName, const char* pstrValue)
	{
		if (strcmp(pstrName, "errorimage") == 0)
		{
			m_errorImage = pstrValue;
		}
		else if (strcmp(pstrName, "loadingimage") == 0)
		{
			m_loadingImage = pstrValue;
		}
		else if (strcmp(pstrName, "loadmaxsize") == 0)
		{
			ParserSize(&m_loadMaxSize,pstrValue);
		}
		else if (strcmp(pstrName, "url") == 0)
		{
			SetUrl(pstrValue);
		}
		else if (strcmp(pstrName, "file") == 0)
		{
			SetFile(pstrValue);
		}
		else {
			ZContainer::SetAttribute(pstrName, pstrValue);
		}
	}


	void ZNetImageControl::SetUrl(const char* url)
	{
		if (m_url == url)
			return;
		m_url = url;
		m_file.Empty();
		m_state = STATE_UNLOAD;
		Invalidate();
	}

	void ZNetImageControl::SetFile(const char* file) {
		if (m_file == file)
			return;
		m_file = file;
		m_url.Empty();
		m_state = STATE_UNLOAD;
		Invalidate();
	}

	void ZNetImageControl::SetErrorImage(const char* image)
	{
		m_errorImage = image;
	}

	void ZNetImageControl::SetLoadingImage(const char* image)
	{
		m_loadingImage = image;
	}

	void ZNetImageControl::Download(const char* url)
	{
		ZString name = ZFileUtils::Instance()->GetDownloadImagePath(zstrhash(m_url));
		if (!ZFileUtils::Instance()->IsFileExist(name))
		{
			ZNetControlDownloaderObserver* obs = this;
			AddRef();
			DownloadTaskPtr task = ZNetControlDownloader::Instance()->
				createDownloadFileTask(m_url.GetString(), name.GetString(), obs);
			if (!task) {
				Release();
				SetState(STATE_ERROR);
			} else {
				SetState(STATE_LOADING);
			}
		}
		else
		{
			//SetState(STATE_LOADING);
			LoadFile(name);
		}
	}


	void ZNetImageControl::LoadFile(const char* path) {
		ZImageFormat format = GetImageFormat(path);
		if (format == IMG_FMT_UNKNOW) {
			//不支持的格式
			ZFileUtils::RemoveFile(path);
			SetState(STATE_ERROR);
			return;
		}

		//设置为成功
		SetState(STATE_OK);

		//检测图片格式
		if (format == IMG_FMT_GIF || format == IMG_FMT_APNG) {
			auto image = CreateControl<ZAnimateImageControl>();
			Add(image);

			image->SetFileAsync(path);
		}
		else{
			auto image = CreateControl<ZImageControl>();
			Add(image);

			image->SetMaxSize(m_loadMaxSize);
			image->SetFileAsync(path);
		}
	}

	void ZNetImageControl::SetState(State state) {
		//清空子控件
		RemoveAll();

		//根据状态重新添加控件
		switch (state) {
			case STATE_OK:
				break;
			case STATE_ERROR:
				break;
			case STATE_LOADING: {
				//添加转圈控件
				auto control = CreateControl<ZLoadingControl>();
				control->SetAutoStart(true);
				control->SetImage(m_loadingImage);
				Add(control);
				break;
			}
		}
		m_state = state;
	}

	//图片下载完毕
	void ZNetImageControl::OnFinishDownload(int errorCode, const char* path)
	{
		if (errorCode == DownloadTask::ERROR_NO_ERROR) {
			LoadFile(path);
		}
		else {
			//下载失败
			SetState(STATE_ERROR);
		}
	}

	void ZNetImageControl::OnDownloadProgress(int percent)
	{

	}


}//namespace
